package com.employment.websocket;

import com.employment.entity.ChatMessage;
import com.employment.service.ChatService;
import com.employment.util.JsonUtil;
import com.employment.security.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket消息处理器
 * 
 * @author employment
 * @since 2024-01-01
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/chat/{token}")
public class ChatWebSocketHandler {
    
    /**
     * 存储每个客户端对应的WebSocket对象
     */
    private static final ConcurrentHashMap<Long, Session> userSessions = new ConcurrentHashMap<>();
    
    private static ChatService chatService;
    
    private static JwtTokenUtil jwtTokenUtil;
    
    /**
     * 注入Service（静态注入）
     */
    @Autowired
    public void setChatService(ChatService chatService) {
        ChatWebSocketHandler.chatService = chatService;
    }
    
    @Autowired
    public void setJwtTokenUtil(JwtTokenUtil jwtTokenUtil) {
        ChatWebSocketHandler.jwtTokenUtil = jwtTokenUtil;
    }
    
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        try {
            // 验证token
            if (jwtTokenUtil == null || !jwtTokenUtil.isTokenValid(token)) {
                log.warn("WebSocket连接失败：Token无效或已过期");
                session.close();
                return;
            }
            
            String username = jwtTokenUtil.getUsernameFromToken(token);
            if (username == null) {
                log.warn("WebSocket连接失败：无法获取用户名");
                session.close();
                return;
            }
            
            // 获取用户ID（这里需要根据username查询用户ID）
            Long userId = getUserIdByUsername(username);
            if (userId == null) {
                log.warn("WebSocket连接失败：用户不存在");
                session.close();
                return;
            }
            
            // 存储会话
            userSessions.put(userId, session);
            log.info("用户{}建立WebSocket连接", userId);
            
        } catch (Exception e) {
            log.error("WebSocket连接异常", e);
            try {
                session.close();
            } catch (IOException ex) {
                log.error("关闭WebSocket连接失败", ex);
            }
        }
    }
    
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("token") String token) {
        try {
            if (jwtTokenUtil != null) {
                String username = jwtTokenUtil.getUsernameFromToken(token);
                Long userId = getUserIdByUsername(username);
                if (userId != null) {
                    userSessions.remove(userId);
                    log.info("用户{}断开WebSocket连接", userId);
                }
            }
        } catch (Exception e) {
            log.error("处理WebSocket关闭异常", e);
        }
    }
    
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("token") String token) {
        try {
            log.info("收到消息：{}", message);
            
            // 验证token并获取用户ID
            if (jwtTokenUtil == null) {
                return;
            }
            
            String username = jwtTokenUtil.getUsernameFromToken(token);
            Long userId = getUserIdByUsername(username);
            if (userId == null) {
                return;
            }
            
            // 解析消息（这里可以定义消息格式，比如JSON）
            // 示例：{"type": "heartbeat"} 或 {"type": "message", "conversationId": 1, "content": "hello"}
            // 这里简单处理心跳消息
            if ("heartbeat".equals(message)) {
                sendMessageToUser(userId, "pong");
                return;
            }
            
            // 其他消息类型可以在这里处理
            log.info("用户{}发送消息：{}", userId, message);
            
        } catch (Exception e) {
            log.error("处理WebSocket消息异常", e);
        }
    }
    
    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误", error);
    }
    
    /**
     * 发送消息给指定用户
     */
    public static void sendMessageToUser(Long userId, String message) {
        Session session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
                log.info("向用户{}发送消息：{}", userId, message);
            } catch (IOException e) {
                log.error("向用户{}发送消息失败", userId, e);
                // 移除失效的会话
                userSessions.remove(userId);
            }
        }
    }
    
    /**
     * 广播消息给会话中的所有用户
     */
    public static void broadcastToConversation(Long conversationId, String message, Long excludeUserId) {
        try {
            // 获取会话中的所有参与者
            // 这里需要调用service获取参与者列表
            // List<Long> participantIds = chatService.getConversationParticipants(conversationId);
            
            // 暂时先记录日志
            log.info("广播消息到会话{}：{}", conversationId, message);
            
        } catch (Exception e) {
            log.error("广播消息异常", e);
        }
    }
    
    /**
     * 推送新消息通知
     */
    public static void pushNewMessage(ChatMessage chatMessage) {
        try {
            String messageJson = JsonUtil.toJson(chatMessage);
            
            // 获取会话参与者并推送消息
            // List<Long> participantIds = chatService.getConversationParticipants(chatMessage.getConversationId());
            // for (Long userId : participantIds) {
            //     if (!userId.equals(chatMessage.getSenderId())) {
            //         sendMessageToUser(userId, messageJson);
            //     }
            // }
            
            log.info("推送新消息：{}", messageJson);
            
        } catch (Exception e) {
            log.error("推送新消息异常", e);
        }
    }
    
    /**
     * 获取在线用户数量
     */
    public static int getOnlineUserCount() {
        return userSessions.size();
    }
    
    /**
     * 获取所有在线用户ID
     */
    public static java.util.Set<Long> getOnlineUserIds() {
        return userSessions.keySet();
    }
    
    /**
     * 根据用户名获取用户ID（临时实现，实际应该调用用户服务）
     */
    private Long getUserIdByUsername(String username) {
        // TODO: 实现用户名到用户ID的转换逻辑
        // 这里暂时返回一个模拟值
        return 1L;
    }
}